package com.itheima.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.bean.Dish;
import com.itheima.bean.DishFlavor;
import com.itheima.common.PageParam;
import com.itheima.dao.DishDao;
import com.itheima.dto.DishDto;
import com.itheima.service.CategoryService;
import com.itheima.service.DishFlavorService;
import com.itheima.service.DishService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Transactional
@Service
public class DishServiceImpl extends ServiceImpl<DishDao, Dish> implements DishService {

    //注入dishflavorservice
    @Autowired
    private DishFlavorService dishFlavorService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private DishService dishService;
    /**
     * 根据分类id和状态值来查询菜品数据，和口味数据
     *
     * @param categoryId
     * @param status
     * @return
     */
    @Override
    public List<DishDto> findByCategoryId(Long categoryId, Integer status) {


        //1. 查询菜品数据
        LambdaQueryWrapper<Dish> lqw = new LambdaQueryWrapper<>();

        // 设置条件。
        lqw.eq(Dish::getCategoryId , categoryId);
        lqw.eq(status != null , Dish::getStatus , status);
        List<Dish> dishList = this.list(lqw);

        //2. 需要构建一个List<DishDto> ，这样就能装Dish对象，也能装口味数据
        return dishList.stream().map(dish -> {

            //1. 创建DishDto
            DishDto dto = new DishDto();

            //2. 拷贝数据，把dish拷贝到dto这里
            BeanUtils.copyProperties(dish , dto);

            //3. 还缺少口味数据
            LambdaQueryWrapper<DishFlavor> dfQW = new LambdaQueryWrapper<>();
            dfQW.eq(DishFlavor::getDishId , dish.getId());
            List<DishFlavor> flavorList = dishFlavorService.list(dfQW);

            dto.setFlavors(flavorList);

            return dto;
        }).collect(Collectors.toList());
    }

    /**
     * 添加菜品
     *  1. 添加菜品稍微有点不一样，因为这份数据要分别往两张表里面存储： dish 表， dish_flavor 表
     *  2. 添加顺序：
     *      2.1 先往菜品表添加数据
     *
     *      2.2 再往口味表添加数据
     *          2.2.1 再添加口味的时候，必须设置这个口味属于哪个菜品，要设置菜品的id。
     *
     * @param dishDto
     * @return
     */
    @Override
    public int add(DishDto dishDto) {

        //1. 先添加菜品:: 只要添加成功，MP 会自动把id填充到对象里面去。
        int row = getBaseMapper().insert(dishDto);

        //2. 后添加口味
        //2.1 得到口味的集合数据。对集合里面的每一个口味都要做dishId的设置工作。 map() 用来映射的。
        /*List<DishFlavor> flavorList = dishDto.getFlavors().stream().map(new Function<DishFlavor, DishFlavor>() {

            @Override
            public DishFlavor apply(DishFlavor dishFlavor) {
                //设置口味属于哪个菜品
                dishFlavor.setDishId(dishDto.getId());
                return dishFlavor;
            }
        }).collect(Collectors.toList());*/
        boolean result = true;
        if(dishDto.getFlavors()!=null && dishDto.getFlavors().size() >0 ){
            List<DishFlavor> flavorList1 = dishDto.getFlavors().stream().map(dishFlavor -> {
                dishFlavor.setDishId(dishDto.getId());
                return dishFlavor;
            }).collect(Collectors.toList());

            result = dishFlavorService.saveBatch(flavorList1);
        }
        return row > 0 && result ? 1 : 0 ;
    }

    /**
     * 菜品分页
     * @param pageParam
     * @return
     */
    @Override
    public IPage<DishDto> page(PageParam pageParam) {

        //1. 先查询出来Dish表的分页数据。

        //1.1 构建分页的对象
        IPage<Dish> page = new Page<>(pageParam.getPage() , pageParam.getPageSize());

        //1.2 构建条件对象
        LambdaQueryWrapper<Dish> lqw = new LambdaQueryWrapper<>();

        //1.3 封装条件
        lqw.like(pageParam.getName() != null , Dish::getName , pageParam.getName());

        //1.4 执行查询操作:: 不能直接返回这个dishPage, 因为它没有分类的名称
        IPage<Dish> dishPage = getBaseMapper().selectPage(page, lqw);

        //2. 需要构建一个IPage<DishDto> ， 直接返回它。

        //2.1 构建一个新的IPage<DishDto>
        IPage<DishDto> dishDtoPage = new Page<>();

        //2.2 考虑给这个dishDtoPage 组装数据： 总记录数， 当前页的集合数。
        dishDtoPage.setTotal(dishPage.getTotal());

        //必须要把dishPage里面的10条数据，映射成10个DishDto，映射之后，要根据分类id去查询分类数据。采用流的方式来做！
        List<DishDto> dtoList = dishPage.getRecords().stream().map(dish -> {
            //a. 构建一个DishDto
            DishDto dishDto = new DishDto();

            //b. 把dish的数据拷贝到dishDto 属性拷贝的方式，把数据拷贝过来
            //参上一：源对象， 参数二： 目标对象。只拷贝同名属性。
            BeanUtils.copyProperties(dish, dishDto);


            //c. 没有分类的数据
            String categoryName = categoryService.findById(dish.getCategoryId()).getName();
            dishDto.setCategoryName(categoryName);


            //d. 没有口味的数据:: 再去查询口味数据，然后封装到dto里面去
            LambdaQueryWrapper<DishFlavor> dfQW = new LambdaQueryWrapper<>();
            dfQW.eq(DishFlavor::getDishId ,dish.getId() );
            List<DishFlavor> flavorList = dishFlavorService.list(dfQW);
            dishDto.setFlavors(flavorList);


            //返回dto对象。
            return dishDto;
        }).collect(Collectors.toList());

        //把集合装到Page对象里面去。
        dishDtoPage.setRecords(dtoList);
        return dishDtoPage;
    }

    /**
     * 更新菜品
     *  1. 更新菜品需要更新两张表的数据：1.菜品表 ，2.菜品口味表
     *  2. 更新菜品表
     *      2.1 更新菜品表，其实很简单，就按照正常的根据id来更新即可
     *  3. 更新口味表
     *      3.1 因为口味的数据变化太大，很难去计较到底是怎么更新的。
     *      3.2 所以可以把这个菜品原来的所有口味都删除掉
     *      3.3 然后把页面传递过来的口味再添加进去即可！
     *
     * @param dishDto
     * @return
     */
    @Override
    public int update(DishDto dishDto) {

        //1. 更新菜品表
        boolean result1 = this.updateById(dishDto);

        //2. 更新口味表

        //2.1 先删除口味
        LambdaQueryWrapper<DishFlavor> lqw = new LambdaQueryWrapper<>();
        lqw.eq(DishFlavor::getDishId , dishDto.getId());
        dishFlavorService.remove(lqw);

        //2.2 再添加口味

        //2.2.1 获取口味的集合
        List<DishFlavor> flavorList = dishDto.getFlavors();

        //2.2.2 判断有没有口味
        boolean result3 = true;
        if( flavorList!=null && flavorList.size() > 0){

            List<DishFlavor> list = flavorList.stream().map(dishFlavor -> {
                //设置口味属于哪个菜品
                dishFlavor.setDishId(dishDto.getId());

                return dishFlavor;
            }).collect(Collectors.toList());

            //保存口味数据
            result3 = dishFlavorService.saveBatch(list);
        }

        //如果菜品更新成功，口味添加也成功，就表示成功！
        return result1 && result3 ? 1 : 0;
    }
    /**
     * 批量删除菜品
     * @param ids
     * @return
     */
    public int delete(Long ids) {
        LambdaQueryWrapper<Dish> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Dish::getCategoryId, ids);
        List<Dish> dishList = dishService.list(lqw);

        int row = getBaseMapper().deleteById(ids);

        return row;
    }



}
